package com.gtmonitor.network;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Calendar;
import java.util.Scanner;
import java.util.regex.MatchResult;

import android.util.Log;

public final class NetworkStat {
	private static int interfaceCount = 0;
	private static InterfaceStat[] delta = null;
	private static InterfaceStat[] lastStats = null;
	private static boolean recording = false;
	private static PrintWriter logFile = null;
	private final static InterfaceStat currentStat = new InterfaceStat();
	private final static String PROC_NET_DEV = "/proc/net/dev";
	private final static String TAG = "GTmonitor";

	static {
		BufferedReader in;
		try {
			// determine # of network interfaces
			in = new BufferedReader(new FileReader(PROC_NET_DEV));
			in.readLine();
			in.readLine();
			while (in.readLine() != null) {
				interfaceCount++;
			}
			in.close();
			// initialize data structures
			lastStats = new InterfaceStat[interfaceCount];
			delta = new InterfaceStat[interfaceCount];
			for (int i = 0; i < interfaceCount; i++) {
				lastStats[i] = new InterfaceStat();
				delta[i] = new InterfaceStat();
			}
			// determine if log can be written
			try {
				logFile = new PrintWriter(makeFileName());
				logFile.println("milliseconds  interface  rx  tx");
			} catch (IOException e) {
				logFile = null;
			}
		} catch (FileNotFoundException e) {
			Log.wtf(TAG,
					"FileNotFoundException in NetworkStat static initializer");
		} catch (IOException e) {
			Log.wtf(TAG, "IOException in NetworkStat static initializer");
		}
	}

	public static void cleanup() {
		if (logFile != null) {
			logFile.close();
		}
	}

	private static String makeFileName() {
		Calendar c = Calendar.getInstance();
		StringBuilder sb = new StringBuilder(64);
		sb.append("/sdcard/gtmonitor/network_").append(c.get(Calendar.YEAR))
				.append('_').append(c.get(Calendar.MONTH) + 1).append('_')
				.append(c.get(Calendar.DAY_OF_MONTH)).append('_')
				.append(c.get(Calendar.HOUR_OF_DAY)).append('_')
				.append(c.get(Calendar.MINUTE)).append('_')
				.append(c.get(Calendar.SECOND)).append(".log");
		return sb.toString();
	}

	public static int getInterfaceCount() {
		return interfaceCount;
	}

	public static boolean isRecording() {
		return recording;
	}

	public static void setRecording(boolean recording) {
		NetworkStat.recording = recording;
	}

	public static InterfaceStat[] getNextDelta() {
		try {
			Scanner s = new Scanner(new File(PROC_NET_DEV));
			// skip the first two lines
			s.nextLine();
			s.nextLine();
			for (int index = 0; index < interfaceCount; ++index) {
				s.findInLine("\\s*(\\w+)\\:\\s+(\\d+)\\s+\\d+\\s+\\d+\\s+\\d+\\s+\\d+\\s+\\d+\\s+\\d+\\s+\\d+\\s+(\\d+)");
				MatchResult r = s.match();
				currentStat.interfaceName = r.group(1);
				currentStat.rxBytes = Long.parseLong(r.group(2));
				currentStat.txBytes = Long.parseLong(r.group(3));

				delta[index].interfaceName = currentStat.interfaceName;
				lastStats[index].interfaceName = currentStat.interfaceName;

				delta[index].rxBytes = currentStat.rxBytes
						- lastStats[index].rxBytes;
				lastStats[index].rxBytes = currentStat.rxBytes;

				delta[index].txBytes = currentStat.txBytes
						- lastStats[index].txBytes;
				lastStats[index].txBytes = currentStat.txBytes;

				s.nextLine();

				if (logFile != null && recording) {
					StringBuilder sb = new StringBuilder(64);
					sb.append(System.currentTimeMillis()).append(' ')
							.append(delta[index].interfaceName).append(' ')
							.append(delta[index].rxBytes).append(' ')
							.append(delta[index].txBytes);
					logFile.println(r.group(1));
				}
			}
			logFile.flush();
			s.close();
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			Log.wtf(TAG, "FileNotFoundException in NetworkStat.getNextDelta()");
		}
		return delta;
	}

	// prevent creation of instances
	private NetworkStat() {
	}
}